<?php


class TimeMachine {
	
	private $chron_ptr;
	private $record_request;
	private $recording_request;
	
	public function __construct() {
		
		$args = func_get_args();
		$args[] = 'history';
		$args_len = count($args);
		$first_index = 0;
		
		$this->chron_ptr = &$_SESSION;
		for ($i=$first_index; $i < $args_len; $i++) {
			if (!isset($this->chron_ptr[$args[$i]])) {
				$this->chron_ptr[$args[$i]] = array();
			}
			
			$this->chron_ptr = &$this->chron_ptr[$args[$i]];
		}
		
		$this->record_request = true;
		$this->recording_request = array();
		
	}
	
	public function clean() {
		$_SESSION[APP_ID]['data'] = array();
		$this->chron_ptr = array();
	}
	
	public function push($req) {
		array_push($this->chron_ptr, $req);
	}

	public function pop() {
		$last = array_pop($this->chron_ptr);
		if ($last == null) {
			return array('ctrl' => DEFAULT_CTRL, 'act' => DEFAULT_ACT);
		}
		return $last;
	}
	
	public function setRecord($v) {
		$this->record_request = $v;
	}
	
	public function setRequest($req) {
		$this->recording_request = $req;
	}
	
	public function Record() {
		if ($this->record_request) {
			$this->push($this->recording_request);
		}
	}

	public function top() {
		return end($this->chron_ptr);
	}
	
	public function back() {
		$last = $this->pop();
		unset($last['ctrl']);
		unset($last['act']);
		$prev = $this->pop();
		$_REQUEST = array_merge($_REQUEST, $prev, $last);
	}
	
	public function cleanError() {
		unset($this->recording_request['showError']);
		unset($this->recording_request['errorMsg']);
	}
	
	public function refresh() {
		$_REQUEST = $this->pop();
		//$this->record_request = false;
		
	}
	
	public function goBack($response_params) {
		
		
		list($ctrl, $act, $reset) = $this->getPrevAct();
		if (!$reset) {
			$this->recording_request = array_merge($this->recording_request, array("ctrl" => $ctrl, "act" => $act));
		} else {
			$this->recording_request =  array("ctrl" => $ctrl, "act" => $act);
		}
		$this->recording_request = array_merge($this->recording_request, $response_params);
		$this->Record();
		ob_clean();
		
		$_REQUEST = array();
		$_REQUEST['ctrl'] = $ctrl;
		$_REQUEST['act'] = $act;
		$_REQUEST['back'] = 1;

		throw new goBackException();
	}
	
	public function reloadBack($response_params) {
	
	
	    list($ctrl, $act, $reset) = $this->getPrevAct();
	    if (!$reset) {
	        $this->recording_request = array_merge($this->recording_request, array("ctrl" => $ctrl, "act" => $act));
	    } else {
	        $this->recording_request =  array("ctrl" => $ctrl, "act" => $act);
	    }
	    $this->recording_request = array_merge($this->recording_request, $response_params);
	    $this->Record();
	    ob_clean();

	
	    echo "<meta http-equiv=\"refresh\" content=\"0; url=index.php?ctrl=$ctrl&act=$act&back=1\">";
	    throw new reloadBackException();
	}	
	
	/**
	 * 
	 * @param Request $request
	 */
	public function goRefresh($response_params = array()) {

		list ($ctrl, $act) = $this->getCurrentAct();
		$this->Record();
		ob_clean();
		
		$_REQUEST = array();
		$_REQUEST['ctrl'] = $ctrl;
		$_REQUEST['act'] = $act;	

		$chron_len = count($this->chron_ptr);
		$this->chron_ptr[$chron_len-1] = array_merge($this->chron_ptr[$chron_len-1],$response_params );
				

		throw new refreshException();
		//echo "<meta http-equiv=\"refresh\" content=\"0; url=index.php?ctrl=$ctrl&act=$act\">";		
	}	
	
	public function reloadRefresh($response_params = array()) {
	
	    list ($ctrl, $act) = $this->getCurrentAct();
	    $this->Record();
	    ob_clean();
	    $chron_len = count($this->chron_ptr);
	    $this->chron_ptr[$chron_len-1] = array_merge($this->chron_ptr[$chron_len-1],$response_params );
	
	    $_REQUEST = array();
	    $_REQUEST['ctrl'] = $ctrl;
	    $_REQUEST['act'] = $act;
	
	    echo "<meta http-equiv=\"refresh\" content=\"0; url=index.php?ctrl=$ctrl&act=$act\">";
	    throw new reloadBackException();
	    
	}	
	
	public function getPrevAct() {
		
		$chron_len = count($this->chron_ptr);
		$reset = false;
		
		if (isset($this->chron_ptr[$chron_len-2])) {
			$ctrl	= $this->chron_ptr[$chron_len-2]['ctrl'];
			$act	= $this->chron_ptr[$chron_len-2]['act'];
		} else {
			$ctrl	= DEFAULT_CTRL;
			$act	= DEFAULT_ACT;
			$reset  = true;
		}

		return array($ctrl, $act, $reset);
	}
	
	public function getCurrentAct() {
	
		$current = $this->top();
		return array($current['ctrl'], $current['act']);
	}	
	
	public function toString() {
		return print_r($this->chron_ptr, true);
	}
	
}




?>